<template>
	<div>多文件上传</div>

	<!-- action: 立即上传 http-request -->

	<el-upload
		class="avatar-uploader"
		action="#"
		:http-request="UploadRequestHandler"
		:limit="300"
		:before-upload="beforeAvatarUpload"
		:on-success="handleAvatarSuccess"
		:on-exceed="handleExceed"
		multiple
		:on-change="handleChange"
	>
		<template #trigger>
			<el-button type="primary">select file</el-button>
		</template>
		<el-button class="ml-3" type="success" @click="submitHandler"> upload to server </el-button>

		<template #tip>
			<div class="el-upload__tip">jpg/png files with a size less than 500kb</div>
		</template>
	</el-upload>
</template>

<script setup>
import { instance } from '@/utils'
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import SparkMD5 from 'spark-md5'

const imageUrl = ref('')
const form = reactive({
	file: null,
	filename: null
})

const handleAvatarSuccess = (response, uploadFile) => {
	// imageUrl.value = URL.createObjectURL(uploadFile.raw)
}

/**
 * 文件超出个数限制时的钩子
 */
const handleExceed = () => {
	ElMessage.error('超出最大上传限制')
}
const fileListData = ref([])
// 覆盖默认行为
const UploadRequestHandler = (params) => {
	imageUrl.value = URL.createObjectURL(params.file)
	form.file = params.file
	form.filename = params.file.name
}
/**
 * 谁对资源进行分快，资源整合 《怎么知道前端已经上传完成》
 * 失败怎么处理
 * 切片上传
 * 断点续传
 * 秒传
 选择上传资源，判断文件大小，大于范围，进行切片，再分片续传
 检查上传文件，断点续传
 前端上传完成后，发送一个merge 请求  
 检查 分片。 分片上传  合并分片
 */
const submitHandler = async () => {}
const changeBuffer = (file) => {
	return new Promise((resolve, reject) => {
		let fileReader = new FileReader()
		fileReader.readAsArrayBuffer(file)
		fileReader.onload = (e) => {
			let buffer = e.target.result,
				spark = new SparkMD5.ArrayBuffer(),
				HASH = spark.append(buffer).end(),
				suffix = file.name.split('.').pop()
			resolve({
				HASH,
				suffix,
				filename: `${HASH}.${suffix}`
			})
		}
	})
}
const handleChange = async (file, fileList) => {
	const uploadFile = file.raw

	// 获取已经上传的文件
	// 获取文件的HASH
	let already = [],
		data = null,
		{ HASH, suffix } = await changeBuffer(uploadFile)
	try {
		// 要做秒传，这里应该还有一个标识，来告诉客户端，
		const data = await instance.get('/upload_already', {
			params: {
				HASH
			}
		})
		if (+data.code === 0) {
			already = data.fileList
		}
	} catch (error) {}

	// // 定义分片大小 固定数量 固定大小？  不过这里还是拿原始数据做计算，不会影响
	let chunkSize = 1024 * 1024 * 5
	// // 计算分片数量
	let chunkNum = Math.ceil(file.size / chunkSize)
	if (chunkNum > 100) {
		chunkSize = file.size / 100
		chunkNum = 100
	}

	console.log('%c [  ]-167', 'font-size:13px; background:pink; color:#bf2c9f;', chunkNum)

	// // 定义分片数组
	const chunks = []
	// 检查上传索引
	let index = 0

	/**
	 * 检查文件
	 * 分片上传
	 */
	while (index < chunkNum) {
		// 生成分片
		const blob = uploadFile.slice(index * chunkSize, (index + 1) * chunkSize)

		// 生成分片对象
		const chunk = {
			file: blob,
			filename: `${HASH}_${index + 1}.${suffix}`
		}
		// 添加到分片数组
		chunks.push(chunk)
		// 更新分片索引 ?
		index++
	}
	index = 0
	const complate = async () => {
		console.log('%c [ index ]-202', 'font-size:13px; background:pink; color:#bf2c9f;', index)
		index++
		if (index < chunkNum) return // 只有全部上传完毕，才merge
		// 合并分片
		// mergeChunk(chunks)
		try {
			data = await instance.post(
				'/upload_merge',
				{
					HASH,
					chunkNum
				},
				{
					headers: {
						'Content-Type': 'application/x-www-form-urlencoded'
					}
				}
			)
			// 等到所有文件都执行完毕，也就是index 和 count 相等的时候 合并文件
			if (+data.code === 0) {
				ElMessage.success('文件上传完毕')
			}
		} catch (error) {
			ElMessage.error('文件上传失败，请稍后重试')
		}
	}

	chunks.forEach(async (chunk) => {
		// 已经上传。无需再传 秒传和续传 都实现了， 很好
		if (already.length && already.includes(chunk.filename)) {
			complate()
			return
		}
		// 如果全部传完，则告诉客户端，全部传递完毕 return 后面的行为
		// 开始上传
		let fm = new FormData()
		fm.append('file', chunk.file)
		fm.append('filename', chunk.filename)
		const data = await instance.post('/upload_chunk', fm)

		if (+data.code === 0) {
			complate()
			return
		}
	})
}
</script>

<style scoped lang="scss">
.upload-wrap {
	border: 1px solid blue;
	width: 50vh;
	height: 100%;

	padding: 10px;
}

.avatar-uploader .avatar {
	width: 178px;
	height: 178px;
	display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
	border: 1px dashed var(--el-border-color);
	border-radius: 6px;
	cursor: pointer;
	position: relative;
	overflow: hidden;
	transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
	border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
	font-size: 28px;
	color: #8c939d;
	width: 178px;
	height: 178px;
	text-align: center;
}
</style>
